unit uShape;

interface

uses
  Graphics, ExtCtrls, Generics.Collections, Vcl.Controls, System.Classes,
  Winapi.Windows, XMLIntf;

type

  TGabrielaShape = class(TShape)
    strict protected
      aDragging: Boolean;
      aDragPoint: TPoint;
      procedure DoMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
      procedure DoMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
      procedure DoMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    public
      constructor Create(paLeft: Integer; paTop: Integer; paParent: TWinControl); reintroduce;
      destructor  Destroy; override;

      procedure Save(paXMLNode: IXMLNode); virtual;
      procedure Load(paXMLNode: IXMLNode); virtual;
  end;

implementation

uses
  SysUtils;

const
  xmlAttLeft = 'Left';
  xmlAttTop  = 'Top';

{ TGabrielaShape }

constructor TGabrielaShape.Create(paLeft: Integer; paTop: Integer; paParent: TWinControl);
begin
  inherited Create(nil);

  Left   := paLeft;
  Top    := paTop;
  Parent := paParent;

  aDragging  := False;
  aDragPoint := Point(0,0);

  OnMouseDown := DoMouseDown;
  OnMouseMove := DoMouseMove;
  OnMouseUp   := DoMouseUp;
end;

destructor TGabrielaShape.Destroy;
begin
  aDragging  := False;
  aDragPoint := Point(0,0);
  inherited;
end;

procedure TGabrielaShape.Load(paXMLNode: IXMLNode);
begin
  Left := paXMLNode.Attributes[xmlAttLeft];
  Top  := paXMLNode.Attributes[xmlAttTop];
end;

procedure TGabrielaShape.DoMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  case Button of
    TMouseButton.mbLeft: begin
      aDragging := True;
      aDragPoint := Point(X,Y);
    end;
    TMouseButton.mbRight: begin
      aDragging := False;
      BringToFront;
    end;
    TMouseButton.mbMiddle: begin
      aDragging := False;
    end;
  end;
end;

procedure TGabrielaShape.DoMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if aDragging
    then begin
      Left := Left + X - aDragPoint.X;
      Top  := Top  + Y - aDragPoint.Y;
    end;
end;

procedure TGabrielaShape.DoMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  aDragging  := False;
  aDragPoint := Point(0,0);
end;

procedure TGabrielaShape.Save(paXMLNode: IXMLNode);
begin
  paXMLNode.Attributes[xmlAttLeft] := Left;
  paXMLNode.Attributes[xmlAttTop]  := Top;
end;

end.
